package org.example.fastproject.core.aspet;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.example.fastproject.core.annotation.OperationLog;
import org.example.fastproject.core.bean.SysUserDetails;
import org.example.fastproject.core.utils.SecurityUtil;
import org.example.fastproject.web.sys.model.SysLog;
import org.example.fastproject.web.sys.service.SysLogService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Objects;

/**
 * @Author 王海舟
 * @Date 2023/1/20 15:01
 * @PackageName:org.example.fastproject.core.aspet
 * @ClassName: LogAspect
 * @Description: 日志切面类
 * @Version 1.0
 */
@Component
@Aspect
@Slf4j
public class LogAspect {
    @Resource
    private SysLogService logService;

    @Around(value = "@annotation(operationLog)")
    public Object around(ProceedingJoinPoint joinPoint, OperationLog operationLog){
        HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String title = operationLog.value();
        String ip = getClientAddress(request);
        String url = request.getRequestURL().toString();
        String method = getMethod(joinPoint);
        Object[] args = joinPoint.getArgs();
        String params = Arrays.toString(args);
        Long start = System.currentTimeMillis();
        Long end = start;
        Object result = null;
        SysLog sysLog = new SysLog();
        sysLog.setTitle(title);
        sysLog.setIp(ip);
        sysLog.setUrl(url);
        sysLog.setMethod(method);
        sysLog.setParams(params);
        try {
            result = joinPoint.proceed(args);
        } catch (Throwable e) {
            sysLog.setType(1);
            sysLog.setException(e.toString());
            throw new RuntimeException(e);
        }finally {
            end = System.currentTimeMillis();
            sysLog.setExecution(end-start);
            SysUserDetails user = SecurityUtil.getUser();
            if(Objects.nonNull(user)){
                sysLog.setCreateUser(user.getId());
                sysLog.setCreateTime(user.getDate());
            }
            logService.saveAsync(sysLog);
        }
        return result;
    }

    /**
     * 获取真实ip地址
     * @param request
     * @return
     */
    public static String getClientAddress(HttpServletRequest request) {
        String address = request.getHeader("X-Forwarded-For");
        if (address != null)
            return address;
        return request.getRemoteAddr();
    }

    /**
     * 获取方法名
     */
    public static  String getMethod(JoinPoint joinPoint){
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        return className+"."+methodName;
    }
}
